using System;
using System.ServiceProcess;
using System.IO;
using EnterpriseDT.Net.Ftp;
using EmailLib;
using System.Collections.Generic;
using System.Xml;

namespace CallExeSrv
{
    public partial class Service1 : ServiceBase
    {
        private static Dictionary<string, string> dict;
        private System.Timers.Timer timer;

        private int spanTime;

        private string logPath;
        private string logPath2;
        private string logPath3;
        private string logPath4Me;
        private string logPath4Pub;
        private string logPath34Pub;
        private string logArchive;

        private string remoteLogPath4Pub;
        private string remoteLogPath4Me;
        private string remotelogPath2;
        private string remotelogPath3;
        private string remoteBasicPath;

        private int lowTmp;
        private int highTmp;
        private int inventoryk;
        private int inventoryd;
        private int ratioTmp;

        private int lowTmpWithOpen;
        private int highTmpWithOpen;

        private static string content = "";
        private static string previousDateTime = "2013-10-22 22:27:17";

        private int addHours;


        public Service1()
        {
            InitializeComponent();
            LoadConfig();
        }

        private void LoadConfig()
        {
            dict = new Dictionary<string, string>();
            XmlDocument doc = new XmlDocument();
            doc.Load(@"D:\vl-docs\config.xml");
            XmlNodeList nodes = doc.GetElementsByTagName("add");
            for (int i = 0; i < nodes.Count; i++)
            {
                string keystr = nodes[i].Attributes["key"].Value.Trim();
                string valuestr = nodes[i].Attributes["value"].Value.Trim();
                dict.Add(keystr, valuestr);
            }
        }

        private static string GetValueByKey(string key)
        {
            foreach (KeyValuePair<string, string> entry in dict)
            {
                if (entry.Key.ToUpper().Trim().Equals(key.ToUpper()))
                    return entry.Value.Trim();
            }
            return "";
        }

        protected override void OnStart(string[] args)
        {
            spanTime = int.Parse(GetValueByKey("spanTime"));
            if (timer == null)
                timer = new System.Timers.Timer();
            timer.Enabled = true;
            timer.Interval = spanTime * 1000;
            timer.Start();
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (timer != null)
                timer.Stop();
            taskBegin();
        }

        private void taskBegin()
        {
            logPath = GetValueByKey("logPath");
            logPath2 = GetValueByKey("logPath2");
            logPath3 = GetValueByKey("logPath3");
            logPath4Me = GetValueByKey("logPath4Me");
            logPath4Pub = GetValueByKey("logPath4Pub");
            logPath34Pub = GetValueByKey("logPath34Pub");
            logArchive = GetValueByKey("logArchive");

            remoteLogPath4Pub = GetValueByKey("RemoteLogPath4Pub");
            remoteLogPath4Me = GetValueByKey("RemoteLogPath4Me");
            remotelogPath2 = GetValueByKey("RemotelogPath2");
            remotelogPath3 = GetValueByKey("RemotelogPath3");
            remoteBasicPath = GetValueByKey("RemoteBasicPath");

            addHours = int.Parse(GetValueByKey("addHours"));
            try
            {
                string tmpdt = lastModifiedDateTime(logPath);
                if (!previousDateTime.Equals(tmpdt))
                {
                    previousDateTime = tmpdt;
                    Random rnd = new Random();
                    int randomN = rnd.Next(50);

                    string[] strlist = FileLoad2Arr(logPath);
                    int len = strlist.Length;
                    string[] pricelist = FileLoad2Arr(logPath3);
                    int len3 = pricelist.Length;

                    if (len > 0 && len <= 3)
                    {
                        int t1 = int.Parse(strlist[len - 1]);
                        int t1Rand = t1 + randomN;
                        string strPrice = pricelist[len3 - 1];
                        LogUtil.writeLog(t1 + ",");
                        LogUtil.writeRand(t1Rand + ",");
                        LogUtil.writePrice(strPrice + ",");
                    }
                    else
                    {
                        int t1 = int.Parse(strlist[len - 1]);
                        int t1Rand = t1 + randomN;
                        string strPrice = pricelist[len3 - 1];
                        LogUtil.writeLog(t1 + ",");
                        LogUtil.writeRand(t1Rand + ",");
                        LogUtil.writePrice(strPrice + ",");

                        int t2 = int.Parse(strlist[len - 2]);
                        int t3 = int.Parse(strlist[len - 3]);
                        int t4 = int.Parse(strlist[len - 4]);

                        #region kk
                        if (t4 > 0 && t3 <= 0 && t2 < 0 && t1 < 0 && inventoryk == 0) //1,0,-1,-2
                        {
                            string[] list = FileLoad2Arr(logPath2);
                            int tk2 = int.Parse(list[len - 2]);
                            int tk3 = int.Parse(list[len - 3]);
                            int tk4 = int.Parse(list[len - 4]);
                            if (tk2 < 0 && tk3 < 0 && tk4 < 0)
                            {
                                int abstk4 = Math.Abs(tk4);
                                int abstk3 = Math.Abs(tk3);
                                int abstk2 = Math.Abs(tk2);
                                //-1, -2, -3 80%
                                if (abstk4 <= abstk3 && abstk3 <= abstk2) StatusKK("98%"); 
                                //-2, -3, -1 100%
                                if (abstk4 <= abstk3 && abstk3 >= abstk2 && abstk4 >= abstk2) StatusKK("97%");
                                //-3, -1, -2 50%
                                if (abstk4 >= abstk3 && abstk3 <= abstk2 && abstk4 >= abstk2) StatusKK("75%");
                                //-2, -1, -3 50%
                                if (abstk4 >= abstk3 && abstk3 <= abstk2 && abstk4 <= abstk2) StatusKK("76%");
                                //-1, -3, -2 33%
                                if (abstk4 <= abstk3 && abstk3 >= abstk2 && abstk4 <= abstk2) StatusKK("80%");
                                //-3, -2, -1 not [kk]
                            }

                        }
                        #endregion

                        #region dk
                        if (t4 < 0 && t3 >= 0 && t2 > 0 && t1 > 0 && inventoryd == 0) //-1, 0, 1, 2
                        {
                            string[] list = FileLoad2Arr(logPath2);
                            int tk2 = int.Parse(list[len - 2]);
                            int tk3 = int.Parse(list[len - 3]);
                            int tk4 = int.Parse(list[len - 4]);
                            if (tk2 > 0 && tk3 > 0 && tk4 > 0)
                            {
                                //1, 2, 3 100%
                                if (tk4 <= tk3 && tk3 <= tk2) StatusDK("99%"); 
                                //2, 1, 3 33%
                                if (tk4 >= tk3 && tk3 <= tk2 && tk4 <= tk2) StatusDK("70%");
                                //1, 3, 2 75%
                                if (tk4 <= tk3 && tk3 >= tk2 && tk4 <= tk2) StatusDK("80%");
                                //2, 3, 1 
                                if (tk4 <= tk3 && tk3 >= tk2 && tk4 >= tk2) StatusDK("84%");
                                //3, 1, 2
                                if (tk4 >= tk3 && tk3 <= tk2 && tk4 >= tk2) StatusDK("85%");
                                //3, 2, 1 not [dk]                                
                            }

                        }
                        #endregion

                        #region KP
                        if (t3 < 0 && t2 < 0 && t1 < 0 && Math.Abs(t1) < Math.Abs(t2) && Math.Abs(t3) < Math.Abs(t2))
                        {
                            lowTmpWithOpen = t2;
                            if (lowTmp < Math.Abs(t2))
                            {
                                lowTmp = t2;
                                if (ratioTmp < Math.Abs(t2))
                                {
                                    ratioTmp = Convert.ToInt32(Math.Abs(t2 * 0.618));
                                }
                                LogUtil.writeLog("[" + ratioTmp + "],");
                            }
                        }


                        if (lowTmp < 0 && inventoryk == 1 && t1 < 0 && t2 < 0 && t3 < 0 && lowTmpWithOpen != 0)
                        {
                            if (Math.Abs(lowTmp) <= ratioTmp)
                            {
                                StatusKP();
                            }
                            else
                            {
                                if (t1 < 0 && t2 < 0 && t3 < 0 && Math.Abs(t1) < ratioTmp && Math.Abs(t2) < ratioTmp && Math.Abs(t3) < ratioTmp)
                                {
                                    StatusKP();
                                }
                            }
                        }
                        #endregion

                        #region dp
                        if (t3 > 0 && t2 > 0 && t1 > 0 && t1 < t2 && t3 < t2)
                        {
                            highTmpWithOpen = t2;
                            if (highTmp < t2)
                            {
                                highTmp = t2;
                                if (ratioTmp < t2)
                                {
                                    ratioTmp = Convert.ToInt32(t2 * 0.618);
                                }
                                LogUtil.writeLog("[" + ratioTmp + "],");
                            }
                        }

                        if (highTmp > 0 && inventoryd == 1 && t1 > 0 && t2 > 0 && t3 > 0 && highTmpWithOpen != 0)
                        {
                            if (highTmp <= ratioTmp)
                            {
                                StatusDP();
                            }
                            else
                            {
                                if (t1 < ratioTmp && t2 < ratioTmp && t3 < ratioTmp)
                                {
                                    StatusDP();
                                }
                            }
                        }
                        #endregion

                    }


                    //ftp log4me and log4pub
                    //ftpLogFile(logPath4Pub, remoteBasicPath, "ru1501.txt");
                    ftpLogFile(logPath34Pub, remoteBasicPath, "ru1501.txt");
                    ftpLogFile(logPath4Pub, remoteLogPath4Pub, "log4pub[" + GetCurrentDateTime(addHours) + "].txt");
                    ftpLogFile(logPath4Me,  remoteLogPath4Me, "log4me[" + GetCurrentDateTime(addHours) + "].txt");
                    ftpLogFile(logPath2, remotelogPath2, "log24me[" + GetCurrentDateTime(addHours) + "].txt");
                    ftpLogFile(logPath3, remotelogPath3, "log34me[" + GetCurrentDateTime(addHours) + "].txt");

                    //Archive log.txt to [D:\vl-docs\_save\log]
                    string f1 = logPath;
                    string f2 = logArchive + "\\" + GetCurrentDateTime(addHours) + ".txt";
                    if (Directory.Exists(logArchive)) File.Copy(f1, f2, true);

                    //send email to gmail
                    if (!content.Equals(""))
                    {
                        sendEmail(content);
                        content = "";
                    }

                }
            }
            catch (Exception e)
            {
                LogUtil.writeLog(e.Message);
            }
            timer.Start();
        }

        #region Status
        private void StatusKK(string percent)
        {
            highTmp = 0;
            inventoryk = 1;
            lowTmpWithOpen = 0;
            LogUtil.writeLog("[kk],");
            LogUtil.writeRand("<font color=green ><b><u>[kk-"+percent+"][" + GetCurrentDateTimeAdvance(addHours) + "]</u></b></font>,");
            LogUtil.writePrice("<font color=green ><b><u>[kk-" + percent + "][" + GetCurrentDateTimeAdvance(addHours) + "]</u></b></font>,");
            content = "[kk-" + percent + "]";
        }

        private void StatusDK(string percent)
        {
            lowTmp = 0;
            inventoryd = 1;
            highTmpWithOpen = 0;
            LogUtil.writeLog("[dk],");
            LogUtil.writeRand("<font color=red ><b><u>[dk-"+percent+"][" + GetCurrentDateTimeAdvance(addHours) + "]</u></b></font>,");
            LogUtil.writePrice("<font color=red ><b><u>[dk-" + percent + "][" + GetCurrentDateTimeAdvance(addHours) + "]</u></b></font>,");
            content = "[dk-" + percent + "]";
        }

        private void StatusKP()
        {
            LogUtil.writeLog("[kp],");
            LogUtil.writeRand("<font color=blue ><b><u>[kp][" + GetCurrentDateTimeAdvance(addHours) + "]</u></b></font>,");
            LogUtil.writePrice("<font color=blue ><b><u>[kp][" + GetCurrentDateTimeAdvance(addHours) + "]</u></b></font>,");
            lowTmp = 0;
            inventoryk = 0;
            lowTmpWithOpen = 0;
            content = "[kp]";
        }

        private void StatusDP()
        {
            LogUtil.writeLog("[dp],");
            LogUtil.writeRand("<font color=blue ><b><u>[dp][" + GetCurrentDateTimeAdvance(addHours) + "]</u></b></font>,");
            LogUtil.writePrice("<font color=blue ><b><u>[dp][" + GetCurrentDateTimeAdvance(addHours) + "]</u></b></font>,");
            highTmp = 0;
            inventoryd = 0;
            highTmpWithOpen = 0;
            content = "[dp]";
        } 
        #endregion

        #region ftpLogFile
        private void ftpLogFile(string localNameWithPath, string remoteDir, string remoteName)
        { 
            FTPConnection ftp = new FTPConnection();
            ftp.ServerAddress =  GetValueByKey("host");
            ftp.UserName = GetValueByKey("user");
            ftp.Password = GetValueByKey("password");
            ftp.Connect();
            ftp.TransferType = FTPTransferType.BINARY;
            if (!ftp.DirectoryExists(remoteDir))
                ftp.CreateDirectory(remoteDir);
            //ftp.ChangeWorkingDirectory("/public_html");
            ftp.UploadFile(localNameWithPath, remoteDir + "//" + remoteName);
            ftp.Close();
        }
        #endregion

        #region sendEmail
        private void sendEmail(string content)
        {
            Email email = new Email();
            email.strSmtpServe = GetValueByKey("strSmtpServe");
            email.strFrom = GetValueByKey("strFrom");
            email.strFromPass = GetValueByKey("strFromPass");
            email.IsHtml = false;
            email.boolEnableSsl = Convert.ToBoolean(1);
            email.iPort = int.Parse(GetValueByKey("iPort"));
            email.SendSMTPEmail(GetValueByKey("strTo"), GetValueByKey("strSubject"), GetValueByKey("strBody")+ content);
        }
        #endregion

        #region lastModifiedDateTime
        private string lastModifiedDateTime(string logPath)
        {
            DateTime dt = File.GetLastWriteTime(logPath);
            return dt.ToString("yyyy-MM-dd HH:mm:ss");
        }
        #endregion

        #region GetCurrentDateTime
        private static string GetCurrentDateTime(int hours)
        {
            DateTime dt = DateTime.Now.AddHours(hours);
            return dt.ToString("yyyyMMdd");
        }

        private static string GetCurrentDateTimeAdvance(int hours)
        {
            DateTime dt = DateTime.Now.AddHours(hours);
            return dt.ToString("yyyyMMdd HH:mm:ss");
        }
        #endregion

        #region FileLoad2Arr
        private string[] FileLoad2Arr(string path)
        {
            string rawData = File.ReadAllText(path);
            char[] splitter = new char[] { ',' };
            string[] strlist = rawData.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
            return strlist;
        } 
        #endregion

        #region OnStop
        protected override void OnStop()
        {
            if (timer != null)
                timer.Stop();
        }
        #endregion
    }
}
